package niu.toy.spring.mvc.helper;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import niu.toy.spring.ioc.BeanFactory;
import niu.toy.spring.ioc.annotation.Autowired;
import niu.toy.spring.mvc.annotation.Action;
import niu.toy.spring.mvc.annotation.Request;
import niu.toy.spring.mvc.HandlerMethod;


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;


/**
 * 创建Action Bean 并填充属性
 * @author niu
 */
public class ActionHelper {

    /**
     * Action Map（HTTP 请求与 Action 方法的映射）
     */
    private static final Map<String, HandlerMethod> actionMap = new LinkedHashMap<String, HandlerMethod>();
    public static  void init(BeanFactory factory) throws Exception {
        Set<Class<?>> actionClassList= new LinkedHashSet<>(3);
        for(String basePackage:factory.getBasePackages()){
            actionClassList.addAll(ClassUtil.scanPackageByAnnotation(basePackage, Action.class));
        }
        // 获取所有 Action 类
        if (CollUtil.isNotEmpty(actionClassList)) {
            // 遍历 Action 类
            for (Class<?> actionClass : actionClassList) {
                // 获取并遍历该 Action 类中所有的方法
                Object actionInstance = actionClass.newInstance();

                populateBean(actionClass,actionInstance,factory);
                Method[] actionMethods = actionClass.getDeclaredMethods();
                if (actionMethods!=null&&actionMethods.length>0) {
                    for (Method actionMethod : actionMethods) {
                        // 处理 Action 方法
                        handleActionMethod(actionInstance, actionMethod);
                    }
                }
            }
        }
    }
    private static void populateBean(Class<?> beanClass,Object   beanInstance,BeanFactory factory){
        Field[]  beanFields=beanClass.getDeclaredFields();
        if(beanFields!=null&&beanFields.length>0){
            for(Field beanField:beanFields){
                if(beanField.isAnnotationPresent(Autowired.class)){
                    Object beanFieldInstance= factory.getBean(beanField.getType());
                    if(beanFieldInstance!=null)
                        ReflectUtil.setFieldValue(beanInstance,beanField,beanFieldInstance);
                }
            }
        }
    }
    private static void handleActionMethod(Object bean, Method actionMethod) {
        // 判断当前 Action 方法是否带有 Request 注解
        if (actionMethod.isAnnotationPresent(Request.Get.class)) {
            String requestPath = actionMethod.getAnnotation(Request.Get.class).value();
            putActionMap("GET", requestPath, bean, actionMethod);
        } else if (actionMethod.isAnnotationPresent(Request.Post.class)) {
            String requestPath = actionMethod.getAnnotation(Request.Post.class).value();
            putActionMap("POST", requestPath, bean, actionMethod);
        }
    }

    private static void putActionMap(String requestMethod, String requestPath, Object bean, Method actionMethod) {
        // 判断 Request Path 中是否带有占位符
        actionMap.put(requestPath+":"+requestMethod, new HandlerMethod(bean, actionMethod));
    }

    /**
     * 获取 Action Map
     */
    public static Map<String, HandlerMethod> getActionMap() {
        return actionMap;
    }
}
